package com.taocyb.framework.security.captcha.kaptcha;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.Random;

import com.google.code.kaptcha.GimpyEngine;
import com.google.code.kaptcha.NoiseProducer;
import com.google.code.kaptcha.util.Configurable;

/**
 * 验证码的样式
 */
public class WaterRipple extends Configurable implements GimpyEngine {
    
   public BufferedImage getDistortedImage(BufferedImage baseImage) {
        
        NoiseProducer noiseProducer = getConfig().getNoiseImpl();
        BufferedImage distortedImage = new BufferedImage(baseImage.getWidth(),
                baseImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = (Graphics2D) distortedImage.getGraphics();
        graphics.drawImage(baseImage, 0, 0, null, null);
        graphics.dispose();
        noiseProducer.makeNoise(distortedImage, .13f, .29f, .34f, .69f);
        noiseProducer.makeNoise(distortedImage, .26f, .35f, .5f, .81f);
        noiseProducer.makeNoise(distortedImage, .24f, .73f, .19f, .55f);
        noiseProducer.makeNoise(distortedImage, .89f, .23f, .44f, .11f);
        makeLineNoise(distortedImage, .1f, .16f, .39f, .25f);
        makeLineNoise(distortedImage, .1f, .25f, .5f, .9f);
        return distortedImage;
    }
    
    public void makeLineNoise(BufferedImage image, float factorOne, float factorTwo, float factorThree,
            float factorFour) {
        Random random = new Random();
        // image size
        int width = image.getWidth();
        int height = image.getHeight();
        // the points where the line changes the stroke and direction
        Point2D[] pts = null;
        // the curve from where the points are taken
        CubicCurve2D cc = new CubicCurve2D.Float(width * factorOne, height * random.nextFloat(), width * factorTwo,
                height * random.nextFloat(), width * factorThree, height * random.nextFloat(), width * factorFour,
                height * random.nextFloat());
        // creates an iterator to define the boundary of the flattened curve
        PathIterator pi = cc.getPathIterator(null,6);
        Point2D tmp[] = new Point2D[350];
        int i = 0;

        // while pi is iterating the curve, adds points to tmp array
        while (!pi.isDone()) {
            float[] coords = new float[5];
            switch (pi.currentSegment(coords)) {
            case PathIterator.SEG_MOVETO:
            case PathIterator.SEG_LINETO:
                tmp[i] = new Point2D.Float(coords[0], coords[1]);
            }
            i++;
            pi.next();
        }

        pts = new Point2D[i];
        System.arraycopy(tmp, 0, pts, 0, i);
        Graphics2D graph = (Graphics2D) image.getGraphics();
        graph.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
        graph.setColor(KaptchaUtils.getRandColor(170,210));
        for (i = 0; i < pts.length - 1; i++) {
            if (i < 3) {
                graph.setStroke(new BasicStroke(0.3f * (4 - i)));
            }
            graph.drawLine((int) pts[i].getX(), (int) pts[i].getY(), (int) pts[i + 1].getX(), (int) pts[i + 1].getY());
        }

        graph.dispose();
    }
}
